use bytes::Bytes;
use g711::G711A;
use tools::{error::Error, ResultEx};
use tracing::{error, trace};

pub(crate) mod g711;
pub(crate) mod rfc2833;

///解码器的枚举
/// 通过这个解码器,可以将数据在多个编码之间互转??
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AudioCodes {
	///原始音频数据
	#[allow(unused)]
	PCM,
	G711A,
	// G711U,
	Rfc2833,
	Unknow,
}

impl AudioCodes {
	///给出对应的采样率
	pub(crate) fn sample_rate(&self) -> u32 {
		match self {
			AudioCodes::PCM => 8000,
			AudioCodes::G711A => 8000,
			AudioCodes::Rfc2833 | AudioCodes::Unknow => 0,
		}
	}

	///从sdp得到格式..因为会有动态的,所以有一部分只能通过名称来得到
	pub(crate) fn from_sdp_type(payload_type: u8, value: &Bytes) -> Self {
		match payload_type {
			8 => AudioCodes::G711A,
			_ if value.starts_with(b"telephone-event/8000") => AudioCodes::Rfc2833,
			_ => {
				trace!("现在还不支持的类型..payload_type:{payload_type},value:{value:?}");
				Self::Unknow
			}
		}
	}

	/// 要写入wav文件的头部的编码类型
	pub(crate) fn to_wav_code_type(&self) -> u8 {
		match self {
			AudioCodes::PCM => 1,
			AudioCodes::G711A => 8,
			AudioCodes::Rfc2833 | AudioCodes::Unknow => {
				error!("不能得到这些编码的类型.{:?}", self);
				0
			}
		}
	}

	/// 要写入wav文件的采样位数
	pub(crate) fn wav_bits(&self) -> u16 {
		match self {
			AudioCodes::PCM => 16,
			AudioCodes::G711A => 8,
			AudioCodes::Rfc2833 | AudioCodes::Unknow => {
				error!("不能得到这些编码的类型.{:?}", self);
				8
			}
		}
	}

	// /// 每次采样字节数
	// pub(crate) fn sample_bytes_size(&self) -> u16 {
	// 	match self {
	// 		AudioCodes::PCM => 2,
	// 		AudioCodes::G711A => 1,
	// 		AudioCodes::Rfc2833 | AudioCodes::Unknow => {
	// 			error!("不能得到这些编码的类型.{:?}", self);
	// 			8
	// 		}
	// 	}
	// }

	///从wav文件的头部得到的格式.转换成编解码器
	pub(crate) fn from_wav_code_type(value: u16) -> ResultEx<Self> {
		match value {
			1 => Ok(AudioCodes::PCM),
			6 => Ok(AudioCodes::G711A),
			_ => Err(Error::IOError(format!("现在还不支持的类型:{value}"))),
		}
	}
	pub fn decode_from_pcm(&self, data: Bytes) -> Bytes {
		match self {
			AudioCodes::PCM => data,
			AudioCodes::G711A => G711A::decode_from_pcm(data),
			AudioCodes::Rfc2833 | AudioCodes::Unknow => data,
		}
	}

	pub fn encode_to_pcm(&self, data: Bytes) -> Bytes {
		match self {
			AudioCodes::PCM => data,
			AudioCodes::G711A => G711A::encode_to_pcm(data),
			AudioCodes::Rfc2833 | AudioCodes::Unknow => data,
		}
	}

	pub(crate) fn packet_size(&self) -> u16 {
		match self {
			AudioCodes::G711A => 160,
			AudioCodes::PCM | AudioCodes::Rfc2833 | AudioCodes::Unknow => 0,
		}
	}
}

pub trait Codec {
	fn decode_from_pcm(data: Bytes) -> Bytes;
	fn encode_to_pcm(data: Bytes) -> Bytes;
}
